package com.ghostflying.cameraonfly;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import android.os.Handler;
import android.util.Log;

public class NetworkService {
	//private final Handler mHandler;
	private int mState;
	
	public static final int STATE_NONE = 0;       // we're doing nothing
	public static final int STATE_LISTEN = 1;     // now listening for incoming connections
	public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
	public static final int STATE_CONNECTED = 3;  // now connected to a remote device
	private static final String TAG = "WLanService";
	private ServerThread mServerThread=null;
	private ConnectThread mConnectThread=null;
	private ConnectedThread mConnectedThread=null;
	private reConnectThread mreConnectThread = null;
	private static final boolean D = true;
	private Handler mhandler = null;
	
	public NetworkService(Handler handler){
		mState=STATE_NONE;
		mhandler = handler;
	}
	private synchronized void setState(int state) {
	      if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
	        mState = state;

	        // Give the new state to the Handler so the UI Activity can update
	 }
	 public synchronized int getState() {           
	       return mState;
	 }
	    
	    public void StartListen(int port){                        
	    	mServerThread=null;
	    	mServerThread=new ServerThread(port);
	    	setState(STATE_LISTEN);
	    	mServerThread.start();
	    	
	    }
	    
	    public synchronized void Connect(String ipadd,int port){
	    	 if (D) Log.d(TAG, "connect to: " +ipadd+port);
	    	 if (mState == STATE_CONNECTING) {
		            if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
		     }
	    	 
	    	 mConnectThread = new ConnectThread(ipadd, port);   
		     mConnectThread.start();
		     setState(STATE_CONNECTING);
	    	
	    }
	    
	    private synchronized void reConnect(String ipadd,int port){
	    	if (D) Log.d(TAG, "reconnect to: " +ipadd+port);	    	
	    	mhandler.obtainMessage(MainActivity.VIDEO_DISCONNECT, -1, -1, null).sendToTarget();
	    	if (mConnectedThread != null){
	    		mConnectedThread.cancel();
	    		mConnectedThread = null;
	    	}
	    	if (mreConnectThread != null){
	    		return;
	    	}
	    	mreConnectThread = new reConnectThread (ipadd,port);	    	
	    	mreConnectThread.start();
	    	setState(STATE_NONE);
	    }
	    
	    private class reConnectThread extends Thread{
	    	String mip;
	    	int mport;
	    	public reConnectThread (String ipadd,int port){
	    		mip = ipadd;
	    		mport = port;
	    	}
	    	
	    	public void run(){
	    		Log.i(TAG, "BEGIN mreConncetThread");
	    		try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	    		synchronized (this){
					mreConnectThread = null;
				}
	    		Connect(mip,mport);	    		
	    	}
	    }
	    
	    public void write(byte[] out) {              
	        // Create temporary object
	        ConnectedThread r;
	        // Synchronize a copy of the ConnectedThread
	        synchronized (this) { 
	            if (mState != STATE_CONNECTED) return; 
	            r = mConnectedThread;
	        }
	        // Perform the write unsynchronized
	        r.write(out);
	    }
	    
	    private class ServerThread extends Thread{             //锟教筹拷锟竭筹拷
	    	int mport;      
	    	ServerSocket mserverSocket=null;
	    	private Socket msocket=null;
	    	public ServerThread(int port){
	    		mport=port;
	    	}
	    	public void run(){
	    		Log.i(TAG, "BEGIN mServertThread");
	    		
	    		try {
					mserverSocket=new ServerSocket(mport);
					
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	    		
	    		while(mState != STATE_CONNECTED){
	    			try {
						msocket = mserverSocket.accept();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
	    			if (msocket!=null){
	    				if (D) Log.d(TAG, "accepted");
	                    synchronized (this) {
	                        switch (mState) {
	                        case STATE_LISTEN:
	                        case STATE_CONNECTING:
	                            // Situation normal. Start the connected thread.                        	
	                            connected(msocket);
	                            break;
	                        case STATE_NONE:
	                        case STATE_CONNECTED:
	                            // Either not ready or already connected. Terminate new socket.
	                            try {
	                                msocket.close();
	                            } catch (IOException e) {
	                     
	                                Log.e(TAG, "Could not close unwanted socket", e);
	                            }
	                            break;
	                        }
	                    }
	    			}
	    		}
	    	}
	    	
	    	public void cancel(){
	    		if (D) Log.d(TAG, "cancel " + this);
	    		try {
					mserverSocket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	    	}
	    	
	    }

		public synchronized void connected(Socket socket) {		
			// TODO Auto-generated method stub
			if (D) Log.e(TAG, "start connected");
	        // Cancel the thread that completed the connection
			if (mConnectThread != null) {			
				mConnectThread.cancel(); mConnectThread = null;
			}

		 // Cancel any thread currently running a connection
			if (mConnectedThread != null){
				mConnectedThread.cancel(); mConnectedThread = null;
			}
			
			if (mServerThread != null) {
				mServerThread.cancel();
				mServerThread = null;
			}
			mConnectedThread = new ConnectedThread(socket);
			mConnectedThread.start();
			//mHandler.obtainMessage(InstrumentControl.MESSAGE_TOAST, 1, -1, R.string.WLAN_connected).sendToTarget();
			setState(STATE_CONNECTED);
		}
		
		private class ConnectThread extends Thread{               //锟斤拷锟斤拷锟竭筹拷  
			private String mipadd;
			private int mport;
			private Socket mSocket;
			public ConnectThread(String ipadd,int port){
				mipadd=ipadd;
				mport=port;
			}
			public void run(){
				try {
					mSocket=new Socket(mipadd,mport);
					//mSocket.setSendBufferSize(32*1024);
				
				} catch (IOException e) {
					try {
						mSocket.close();						
					} catch (Exception e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
						reConnect(mipadd,mport);
					}
				}
				synchronized (this){
					mConnectThread = null;
				}
				if (mSocket != null){
					connected(mSocket);
				}
				
				
			}

			public void cancel() {
				// TODO Auto-generated method stub
				try {
					mSocket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
		
		private class ConnectedThread extends Thread{      //锟斤拷锟斤拷锟斤拷锟斤拷锟竭筹拷
			private Socket mSocket;
			private  InputStream mmInStream;
		    private  OutputStream mmOutStream;

			public ConnectedThread(Socket socket) {           
				// TODO Auto-generated constructor stub
				mSocket = socket;
				InputStream tmpIn = null;
		        OutputStream tmpOut = null;
		        
		        if(mSocket==null){
		        	//mHandler.obtainMessage(InstrumentControl.MESSAGE_TOAST, 1, -1,  R.string.WLAN_add_error).sendToTarget();
		        }
		        else {
		        	try {
						tmpIn = mSocket.getInputStream();            //锟斤拷锟斤拷锟斤拷锟斤拷锟�						
						tmpOut = mSocket.getOutputStream();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
		        }
		        
		        mmInStream = tmpIn;     
		        mmOutStream = tmpOut;
		        
	            
			}
		     public void run(){
		    	Log.i(TAG, "BEGIN mConnectedThread");
		    	byte[] buffer = new byte[1024];
		    	int bytes;
		    	mhandler.obtainMessage(MainActivity.CONNECT_TO_TABLET_VIDEO_SUCC, -1, -1, null).sendToTarget();
		    	while (true){
		    		try {
						bytes = mmInStream.read(buffer);
/*						if (bytes < 0){
		    				reConnect(mSocket.getInetAddress().getHostAddress(),mSocket.getPort());
		    				break;
						}*/
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
/*						if (e.getMessage() == null || e.getMessage().equals("recvfrom failed: ETIMEDOUT (Connection timed out)")){
							reConnect(mSocket.getInetAddress().getHostAddress(),mSocket.getPort());
							//Log.e(TAG, e.getMessage());
						}						
						break;*/
					}
		    		
		    	}
/*		    	while(true){
		    		try {
		    			//bytes = mmInStream.read(buffer);	    			
		    			//mHandler.obtainMessage(InstrumentControl.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
		    			//mhandler.obtainMessage(MainActivity.COMMAND_GET, bytes, -1, buffer).sendToTarget();
		    			
						//String writeMessage=new String(buffer);
						//System.out.println(writeMessage);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						reConnect(mSocket.getInetAddress().toString(),mSocket.getPort());
						break;
					}
		    	 }*/
		     }
		     
		     public void write(byte[] buffer) {            //write锟斤拷锟斤拷byte
		    	 try {
		    		 Log.e(TAG, "start write ");
/*		    		 if(!mSocket.isConnected()){
		    			 Log.e(TAG, "111 ");
		    		 }*/		    		 
		    		 mmOutStream.write(buffer);	                
		    	 } catch (Exception e) {
		    		 Log.e(TAG, "Exception during write", e);
		    		 e.printStackTrace();
		    		 reConnect(mSocket.getInetAddress().getHostAddress(),mSocket.getPort());
		    	 }
		     }

			public void cancel() {                 //锟截憋拷socket
				// TODO Auto-generated method stub
				try {
					mSocket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
	

}
